package com.demo2do.fms.admin.web.controller.authority.infrastructure;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.utils.WebUtils;
import com.demo2do.fms.admin.entity.search.supplier.SupplierSearch;
import com.demo2do.fms.admin.service.DataService;
import com.demo2do.fms.admin.service.authority.UserService;
import com.demo2do.fms.admin.service.supplier.SupplierService;
import com.demo2do.fms.admin.web.resolver.Secure;
import com.demo2do.fms.entity.authority.Branch;
import com.demo2do.fms.entity.authority.User;
import com.demo2do.fms.entity.supplier.SupplierSource;
import com.demo2do.fms.entity.supplier.common.Level;
import com.demo2do.fms.entity.supplier.common.Supplier;
import com.demo2do.fms.entity.supplier.common.Type;

/**
 * 服务供方
 * 
 * @author zhonghui
 * 
 */
@Controller
@RequestMapping("/suppliers")
@MenuSetting("menu-authority")
public class SupplierController {
    
    private static final Logger logger = LoggerFactory.getLogger(SupplierController.class);

    @Autowired
    private SupplierService supplierService;
    
    @Autowired
    @Qualifier("dataService")
    private DataService<Branch> branchService;
    
    @Autowired
    private UserService userService;

    /**
     * 服务供方列表
     * 
     * @param page
     * @param request
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET)
    @MenuSetting("submenu-service-supplier")
    public ModelAndView list(Page page, HttpServletRequest request) {

        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-list");

        int totals = supplierService.count(Supplier.class);
        if(totals > 0){

            List<Supplier> suppliers = supplierService.list(page.with(totals));
            modelAndView.addObject("suppliers", suppliers);
            
            modelAndView.addObject("page", page);
            modelAndView.addObject("queryString", WebUtils.extractQueryString(request, "page", "filter"));
            
        }

        return modelAndView;
        
    }

    /**
     * search 服务供方列表查询
     *
     * @return
     */
    @RequestMapping(value = "/search", method = RequestMethod.GET)
    @MenuSetting("submenu-service-supplier")
    public ModelAndView search() {
        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-search");
        return modelAndView;
    }

    /**
     * onSearch
     * 
     * @param supplierSearch
     * @param page
     * @param request
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET, params = "filter")
    @MenuSetting("submenu-service-supplier")
    public ModelAndView onSearch(SupplierSearch supplierSearch, Page page, HttpServletRequest request) {

        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-list");

        int totals = supplierService.count(Supplier.class, supplierSearch.getFilter());
        if(totals > 0){

            List<Supplier> suppliers = supplierService.search(Supplier.class, supplierSearch, page.with(totals));
            modelAndView.addObject("suppliers", suppliers);
            
            modelAndView.addObject("page", page);
            modelAndView.addObject("queryString", WebUtils.extractQueryString(request, "page", "filter"));
            
        }

        return modelAndView;
        
    }

    /**
     * 引入服务供方
     *
     * @return
     */
    @RequestMapping(value = "/introduce", method = RequestMethod.GET)
    @MenuSetting("submenu-service-supplier")
    public ModelAndView introduce() {

        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-introduce");

        List<Supplier> firstLevelSuppliers = supplierService.list(Level.FIRST);
        modelAndView.addObject("firstLevelSuppliers", firstLevelSuppliers);
        
        return modelAndView;
        
    }

    /**
     * 获取MDM供方信息
     *
     * @param type
     * @param code
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET, params = "prepare", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onPrepare(@RequestParam("type") Type type, @RequestParam("code") String code){

        HttpResult httpResult = new HttpResult();
        
        try {
            
            // search supplier according to type and code
            List<SupplierSource> suppliers = supplierService.obtain(type, code);
            
            // put data back to page
            httpResult.success().data("supplierSources", suppliers);
            
        } catch (BusinessException e) {
            logger.error("#onPrepare() - prepare search fail, exception = [{}]", e);
            httpResult.fail(e.getCode()).message(e.getMessage());
        }
        
        return httpResult;
        
    }

    /**
     * onIntroduce 引入
     * 
     * @param supplier
     * @param parentId
     * @param operator
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onIntroduce(Supplier supplier,
                                                @RequestParam(name = "parentId", required = false) Long parentId,
                                                @Secure(property = "id") Long operator) {

        HttpResult httpResult = new HttpResult();

        try {
            
            supplierService.create(supplier, parentId, operator);

            httpResult.success().message("引入成功！");
            
        } catch (Exception e) {
            logger.error("#onIntroduce() - introduce fail, exception = [{}]", e);
            httpResult.fail("500").message("引入失败! " + e.getMessage());
        }

        return httpResult;
        
    }
    
    /**
     * 修改供方级别
     * 
     * @param supplierId
     * @return
     */
    @RequestMapping(value = "/{supplierId}/change-level", method = RequestMethod.GET)
    public ModelAndView changeLevel(@PathVariable("supplierId") Long supplierId) {
        
        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-change-level");
        
        Supplier supplier = supplierService.load(Supplier.class, supplierId);
        modelAndView.addObject("supplier", supplier);
        
        if (supplier.isFirst()) {            // 一级供方变二级供方
            
            List<Supplier> suppliers = supplierService.list(Level.FIRST, supplier.getType()); 
            modelAndView.addObject("suppliers", suppliers);
            
            List<Supplier> subSuppliers = supplierService.listSponsoredSupplier(supplier);
            modelAndView.addObject("subSuppliers", subSuppliers);
            
            List<User> users = userService.list(supplier);
            modelAndView.addObject("users", users);
            
        } else {                            // 二级供方变一级供方
            
            List<User> users = userService.list(supplier);
            modelAndView.addObject("users", users);
            
        }
        
        
        return modelAndView;
        
    }
    
    /**
     * 修改供方级别
     * 
     * @param operator
     * @param supplierId
     * @param parents
     * @return
     */
    @RequestMapping(value = "/{supplierId}/change-level", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onChangeLevel(@Secure(property = "id") Long operator, 
                                                  @PathVariable("supplierId") Long supplierId,
                                                  @RequestParam(name = "parents", required = false) List<Long> parents) {
    
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Supplier supplier = supplierService.load(Supplier.class, supplierId);
            supplierService.changeLevel(supplier, parents, operator);
            
            httpResult.success().message("修改供方级别成功");
            
        } catch (Exception e) {
            logger.error("#onChangeLevel() - change level fail, exception = [{}]", e);
            httpResult.fail("500").message("修改供方级别失败! " + e.getMessage());
        }
        
        return httpResult;
        
    }
    
    /**
     * 更改上级供方
     * 
     * @param supplierId
     * @return
     */
    @RequestMapping(value = "/{supplierId}/change-parent", method = RequestMethod.GET)
    public ModelAndView changeParent(@PathVariable("supplierId") Long supplierId) {
        
        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-change-parent");
        
        // 1. load current supplier
        Supplier supplier = supplierService.load(Supplier.class, supplierId);
        modelAndView.addObject("supplier", supplier);
        
        // 2. list parent suppliers
        List<Supplier> parents = supplierService.listParentSupplier(supplier);
        modelAndView.addObject("parents", parents);
        
        // 3. list first suppliers
        List<Supplier> suppliers = supplierService.list(Level.FIRST, supplier.getType()); 
        modelAndView.addObject("suppliers", suppliers);
        
        return modelAndView;
        
    }
    
    /**
     * 更改上级供方
     * 
     * @param supplierId
     * @param parents
     * @param operator
     * @return
     */
    @RequestMapping(value = "/{supplierId}/change-parent", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onChangeParent(@PathVariable("supplierId") Long supplierId,
                                                   @RequestParam("parents") List<Long> parents,
                                                   @Secure(property = "id") Long operator) {
        
        HttpResult httpResult = new HttpResult();
        
        try {

            Supplier supplier = supplierService.load(Supplier.class, supplierId);
            supplierService.changeParent(supplier, parents, operator);
            
            httpResult.success().message("更改上级供方成功");
            
        } catch (Exception e) {
            httpResult.fail("500").message("更改上级供方失败");
            logger.error("#onChangeParent() - ", e);
        }
        
        return httpResult;
        
    }
    
    /**
     * 更改默认分区
     * 
     * @param supplierId
     * @return
     */
    @RequestMapping(value = "/{supplierId}/change-branch", method = RequestMethod.GET)
    public ModelAndView changeBranch(@PathVariable("supplierId") Long supplierId) {
        
        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-change-branch");
        
        modelAndView.addObject("supplierId", supplierId);
        
        return modelAndView;
        
    }
    
    /**
     * 更改默认分区
     * 
     * @param supplierId
     * @param branchId
     * @param operator
     * @return
     */
    @RequestMapping(value = "/{supplierId}/change-branch", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onChangeBranch(@PathVariable("supplierId") Long supplierId,
                                                   @RequestParam("branchId") String branchId,
                                                   @Secure(property = "id") Long operator) {
        
        HttpResult httpResult = new HttpResult();
        
        try {

            Supplier supplier = supplierService.load(Supplier.class, supplierId);
            Branch branch = branchService.load(Branch.class, branchId);
            
            supplierService.changeBranch(supplier, branch, operator);
            
            httpResult.success().message("修改默认分区成功");
            
        } catch (Exception e) {
            httpResult.fail("500").message("修改默认分区失败");
            logger.error("#onChangeParent() - ", e);
        }
        
        return httpResult;
    }
    
    /**
     * 同步简称panel
     * 
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}/sync-shortname", method = RequestMethod.GET)
    public ModelAndView syncShortname(@PathVariable("id") Long id) {
        
        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-sync-shortname");
        
        modelAndView.addObject("id", id);
        
        return modelAndView;
        
    }
    
    /**
     * 同步简称
     * 
     * @param id
     * @param operator
     * @return
     */
    @RequestMapping(value = "/{id}/sync-shortname", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onSyncShortname(@PathVariable("id") Long id, @Secure(property = "id") Long operator) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Supplier supplier = supplierService.load(Supplier.class, id);
            supplierService.syncShortname(supplier, operator);
            
            httpResult.success().message("同步成功");
            
        } catch (Exception e) {
            logger.error("#onSyncShortname() - sync fail, exception={}", e);
            httpResult.fail("500").message("同步失败");
        }
        
        return httpResult;
        
    }
    
    /**
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}/delete", method = RequestMethod.GET)
    public ModelAndView delete(@PathVariable("id") Long id) {
        
        ModelAndView modelAndView = new ModelAndView("authority/infrastructure/supplier/supplier-delete");
        
        modelAndView.addObject("id", id);
        
        return modelAndView;
        
    }
    
    /**
     * @param id
     * @param operator
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onDelete(@PathVariable("id") Long id, 
                                             @Secure(property = "id") Long operator) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Supplier supplier = supplierService.load(Supplier.class, id);
            supplierService.delete(supplier, operator);
            
            httpResult.success().message("删除成功");
            
        } catch (BusinessException e) {
            httpResult.fail("500").message(e.getMessage());
            logger.error("#onDelete() - delete fail, business exception = [{}]", e);
        } catch (Exception e) {
            httpResult.fail("500").message("删除失败");
            logger.error("#onDelete() - delete fail, exception = [{}]", e);
        }
        
        return httpResult;
        
    }

}
